#include "localsocket.hpp"
#include <sys/poll.h>

namespace Local_Pool
{

    class PoolServer
    {
        const static int _maxsize = 4096;
        const static int _defaultfd = -1;

    public:
        /**************构造析构************** */
        PoolServer(int port)
            : _listensock(std::make_unique<Local_Socket::TcpSocket>()),
              _isrunning(false)
        {
            _listensock->ServerTcpMod(port);
            for (int i = 0; i < _maxsize; i++)
            {
                _fds[i].fd = _defaultfd;
                _fds[i].events = 0;
                _fds[i].revents = 0;
            }
            _fds[0].fd = _listensock->GetFd();
            _fds[0].events = POLLIN;
        }
        ~PoolServer() {}
        /**************成员函数************** */
        void Start()
        {
            int lo_timeout = -1; // 阻塞或定时轮训

            _isrunning = true;
            while (_isrunning)
            {
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "开始循环";

                // Debug
                printarr(_fds, _maxsize);
                // 1.poll调用

                int ret_pol = poll(_fds, _maxsize, lo_timeout);

                // 2.事件处理
                switch (ret_pol)
                {
                case -1:
                    Local_Log::LOG(Local_Log::LogLever::LERROR) << "poll error ";
                    break;
                case 0:
                    Local_Log::LOG(Local_Log::LogLever::LINFO) << "poll time out... ";
                    break;
                default:
                    Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "poll 监听到了事件... -> ret_sel: " << ret_pol;
                    Dispatcher(); // 处理就绪的事件啊！
                    break;
                }

                Local_Log::LOG(Local_Log::LogLever::LINFO) << "结束循环";
            }
            _isrunning = false;
        }
        void Stop()
        {
            _isrunning = false;
        }
        /**************事件函数************** */
        // 事件派发器
        void Dispatcher()
        {
            for (int i = 0; i < _maxsize; i++)
            {
                // 过滤掉无效文件描述符
                if (_fds[i].fd == _defaultfd)
                    continue;
                // 通过revents判断
                if (_fds[i].revents & POLLIN)
                {
                    if (_fds[i].fd == _listensock->GetFd())
                    {
                        // listensockfd 新连接到来
                        Accepter();
                    }
                    else
                    {
                        // 普通的读事件就绪
                        Recver(i);
                    }
                }
            }
        }
        // 链接管理器
        void Accepter()
        {
            Local_Inetaddr::Inetaddr client;
            int lo_sockfd = _listensock->AcceptGetAndCreate(&client);
            if (lo_sockfd >= 0)
            {
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "accept success";
                int pos = 0;
                for (; pos < _maxsize; pos++)
                {
                    // 过滤掉无效文件描述符
                    if (_fds[pos].fd == _defaultfd)
                        break;
                }
                // 如果pos > _maxsize代表，select监控满了
                if (pos >= _maxsize)
                {
                    // 关闭文件描述符，并结束
                    Local_Log::LOG(Local_Log::LogLever::LWARNING) << "select server full";
                    close(lo_sockfd);
                }
                else
                {
                    // 添加文件描述符给pool
                    _fds[pos].fd = lo_sockfd;
                    _fds[pos].events = POLLIN;
                    _fds[pos].revents = 0;
                }
            }
        }
        // IO处理器
        void Recver(int pos)
        {
            // 读取文件内容
            char lo_buffer[1024];
            int ret_rec = recv(_fds[pos].fd, lo_buffer, sizeof(lo_buffer) - 1, 0);
            if (ret_rec > 0)
            {
                // 读取完成打印
                lo_buffer[ret_rec] = 0;
                std::cout << "client say@ " << lo_buffer << std::endl;
            }
            else if (ret_rec == 0)
            {
                // 文件描述符退出
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "client exit";
                // 移除出数组
                close(_fds[pos].fd);
                // 不要让select在关系这个fd了
                _fds[pos].fd = _defaultfd;
                _fds[pos].events = 0;
                _fds[pos].revents = 0;
            }
            else // if (ret_rec < 0)
            {
                // 读取错误
                Local_Log::LOG(Local_Log::LogLever::LERROR) << "recv error";
                // 移除出数组
                close(_fds[pos].fd);
                // 不要让select在关系这个fd了
                _fds[pos].fd = _defaultfd;
                _fds[pos].events = 0;
                _fds[pos].revents = 0;
            }
        }
        /**************GetSet************** */
        /**************Debug************** */
        void printarr(struct pollfd *arr, int len)
        {
            std::cout << "struct pollfd fd:> ";
            for (int i = 0; i < _maxsize; i++)
            {
                if (arr[i].fd != _defaultfd)
                {
                    std::cout << arr[i].fd << " ";
                }
            }
            std::cout << std::endl;
        }

    private:
        std::unique_ptr<Local_Socket::Socket> _listensock;
        bool _isrunning;

        struct pollfd _fds[_maxsize];
        // struct pollfd *_fds;
    };

}